﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="GestureTest.xaml.cs" company="arvystate.net">
//   arvystate.net
// </copyright>
// <summary>
//   Interaction logic for GestureTest.xaml
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace PresentationAid.Dialog
{
    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Media.Imaging;

    using Microsoft.Kinect;

    using NLog;

    using PresentationAid.Core;
    using PresentationAid.Lib.Enums;
    using PresentationAid.Lib.Gestures;

    /// <summary>
    /// Interaction logic for GestureTest
    /// </summary>
    public partial class GestureTest
    {
        #region Static Fields

        /// <summary>
        /// The logger.
        /// </summary>
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        #endregion

        #region Fields

        /// <summary>
        /// The _current step.
        /// </summary>
        private int currentStep;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="GestureTest"/> class.
        /// </summary>
        public GestureTest()
        {
            Logger.Trace("Init: GestureTest");

            this.InitializeComponent();

            this.SetStep();
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The display not tracking notice.
        /// </summary>
        public void DisplayNotTrackingNotice()
        {
            if (KinectSensorManager.Instance.IsRunning)
            {
                this.GestureTitle.Text = "MOVE IN FRONT OF THE SENSOR!";
                this.GestureDescription.Text = "Kinect™ Sensor cannot see you, please stand in front of the sensor.";
                this.SetImage("no");
            }
            else
            {
                this.GestureTitle.Text = "CONNECT THE SENSOR!";
                this.GestureDescription.Text =
                    "Selected Kinect™ Sensor is currently offline, please select another on the Kinect tab or connect a working sensor to your computer USB port.";
                this.SetImage("no");
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Displays step
        /// </summary>
        /// <param name="step">
        /// Step to display.
        /// </param>
        private void DisplayStep(int step)
        {
            switch (step)
            {
                case 1:
                    this.GestureTitle.Text = "EXCELLENT! NOW SWIPE YOUR RIGHT HAND LEFT";
                    this.GestureDescription.Text =
                        "Every move needs some practice, so try making a slow and wide move from right to left with your right hand.";

                    this.SetImage("swiperight");
                    break;
                case 2:
                    this.GestureTitle.Text = "GOOD JOB! TRY AGAIN WITH YOUR LEFT HAND";
                    this.GestureDescription.Text =
                        "This time try swiping your left hand to the right side. This move usually represents a back action.";

                    this.SetImage("swipeleft");
                    break;
                case 3:
                    this.GestureTitle.Text = "PERFECT! NOW PUT YOUR HANDS TOGETHER";
                    this.GestureDescription.Text =
                        "Slowly put your hands together in front of your body. Try moving them up and down slowly.";

                    this.SetImage("joinedhands");
                    break;
                case 4:
                    this.GestureTitle.Text = "CONGRATIULATIONS!";
                    this.GestureDescription.Text =
                        "You have now learned all available gestures. Put your hands together to start again or wave to quit.";

                    this.SetImage("wave");
                    break;
                default:
                    this.GestureTitle.Text = "START BY WAVING YOUR HAND";
                    this.GestureDescription.Text =
                        "You can use either hand and it should be on approximately same height as your head. Wave gesture usually means hello.";
                    this.SetImage("wave");

                    break;
            }
        }

        /// <summary>
        /// The on gesture recognized.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="gestureEventArgs">
        /// The gesture event args.
        /// </param>
        private void OnGestureRecognized(object sender, GestureEventArgs gestureEventArgs)
        {
            Logger.Info(
                "Event: GestureRecognized - Gesture: {0}, TrackingId: {1}, CurrentStep: {2}", 
                gestureEventArgs.Command.ToString(), 
                gestureEventArgs.TrackingId, 
                this.currentStep);

            switch (this.currentStep)
            {
                case 1:
                    if (gestureEventArgs.Command == GestureCommand.SwipeRight)
                    {
                        Logger.Debug("EventDetail: CorrectGesture - CurrentStepIncrease");

                        this.currentStep++;
                    }
                    else
                    {
                        Logger.Debug("EventDetail: WrongGesture");
                    }

                    break;
                case 2:
                    if (gestureEventArgs.Command == GestureCommand.SwipeLeft)
                    {
                        Logger.Debug("EventDetail: CorrectGesture - CurrentStepIncrease");

                        this.currentStep++;
                    }
                    else
                    {
                        Logger.Debug("EventDetail: WrongGesture");
                    }

                    break;
                case 3:
                    if (gestureEventArgs.Command == GestureCommand.JoinedHands)
                    {
                        Logger.Debug("EventDetail: CorrectGesture - CurrentStepIncrease");

                        this.currentStep++;
                    }
                    else
                    {
                        Logger.Debug("EventDetail: WrongGesture");
                    }

                    break;
                case 4:
                    if (gestureEventArgs.Command == GestureCommand.Wave)
                    {
                        Logger.Debug("EventDetail: CloseGestureWindow - CorrectStep=0");

                        MainWindow window = (MainWindow)Application.Current.MainWindow;
                        window.CloseGestureWindow();
                        window.Activate();

                        this.currentStep = 0;
                    }
                    else if (gestureEventArgs.Command == GestureCommand.JoinedHands)
                    {
                        Logger.Debug("EventDetail: ResetGestureWindow - CorrectStep=0");

                        this.currentStep = 0;
                    }

                    break;
                default:
                    if (gestureEventArgs.Command == GestureCommand.Wave)
                    {
                        Logger.Debug("EventDetail: CorrectGesture - CurrentStepIncrease");

                        this.currentStep++;
                    }
                    else
                    {
                        Logger.Debug("EventDetail: WrongGesture");
                    }

                    break;
            }

            this.SetStep();
        }

        /// <summary>
        /// The on skeleton frame ready.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="args">
        /// The args.
        /// </param>
        private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs args)
        {
            if (!KinectSensorManager.Instance.IsTracking)
            {
                this.DisplayNotTrackingNotice();
            }
        }

        /// <summary>
        /// The set image.
        /// </summary>
        /// <param name="gestureImage">
        /// The gesture image.
        /// </param>
        private void SetImage(string gestureImage)
        {
            BitmapImage image =
                new BitmapImage(
                    new Uri(
                        "/PresentationAid;component/Resources/Images/Gestures/" + gestureImage + "-gesture.png", 
                        UriKind.RelativeOrAbsolute));

            this.GestureImage.Source = image;
        }

        /// <summary>
        /// Sets gesture dialog step
        /// </summary>
        private void SetStep()
        {
            if (KinectSensorManager.Instance.IsTracking)
            {
                this.DisplayStep(this.currentStep);
            }
            else
            {
                this.DisplayNotTrackingNotice();
            }
        }

        /// <summary>
        /// The window activated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void WindowActivated(object sender, EventArgs e)
        {
            KinectSensorManager.Instance.GestureRecognized += this.OnGestureRecognized;
            KinectSensorManager.Instance.SkeletonFrameReady += this.OnSkeletonFrameReady;

            this.SetStep();
        }

        /// <summary>
        /// The window closing.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void WindowClosing(object sender, CancelEventArgs e)
        {
            MainWindow window = (MainWindow)Application.Current.MainWindow;

            if (window == null)
            {
                return;
            }

            window.CloseGestureWindow();
            window.Activate();

            e.Cancel = true;
        }

        /// <summary>
        /// The window deactivated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void WindowDeactivated(object sender, EventArgs e)
        {
            // Clean events, so we do not update window unless it is active.
            KinectSensorManager.Instance.GestureRecognized -= this.OnGestureRecognized;
            KinectSensorManager.Instance.SkeletonFrameReady -= this.OnSkeletonFrameReady;
        }

        #endregion
    }
}